home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
circuits
/
irsim-ca.2
/
irsim-ca
/
irsim-cap-9.2
/
src
/
irsim
/
binsim.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-15
|
13KB
|
559 lines
/*
* *********************************************************************
* * Copyright (C) 1988, 1990 Stanford University. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. Stanford University *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
/*
* The routines in this file handle binary network files input/output.
*/
#include <stdio.h>
#include "defs.h"
#include "net.h"
#include "globals.h"
#include "bin_io.h"
#include "net_macros.h"
private FILE *fnet; /* file for reading/writing network */
private tptr rd_tlist; /* list of transistor just read */
private double inet_CTGA; /* transistor capacitances */
private double inet_CTDE;
private double inet_CTDW;
private long inet_lambda;
private void adjust_transistors();
private char netHeader[] = "<<inet>>";
private char endAscii[] = "<end>\n";
#define CM_M 100.0 /* centimicrons per micron */
#define CM_M2 ( CM_M * CM_M ) /* centimicrons per micron ^ 2 */
#define HEADER_LEN (sizeof( netHeader ) - 1)
/* define number of bytes used to write/read network parameter */
#define NB_NDINDEX 4
#define NB_NCAP 4
#define NB_TSIZE 4
#define NB_COORD 4
#define NB_VTHRESH 2
#define NB_TP 2
#define NB_STRLEN 2
#define NB_FLAGS 1
#define NB_TTYPE 1
/* node flags we are interested in preserving */
#define SAVE_FLAGS (POWER_RAIL | ALIAS | USERDELAY)
/* scale factors for floating-point numbers */
#define VTH_SCALE 1000.0
#define CAP_SCALE 16384.0 /* power of 2 to minimize error */
typedef struct /* format of node records in net file */
{
union
{
char cap[ NB_NCAP ];
char alias[ NB_NDINDEX ];
} n;
char flags[ NB_FLAGS ];
char slen[ NB_STRLEN ];
} File_Node;
#define Size_File_Node ( NB_NDINDEX + NB_FLAGS + NB_STRLEN )
typedef struct /* format of node user-delays in net file */
{
char tphl[ NB_TP ];
char tplh[ NB_TP ];
} File_Delay;
#define Size_File_Delay ( NB_TP + NB_TP )
typedef struct /* format of node thresholds in net file */
{
char vhigh[ NB_VTHRESH ];
char vlow[ NB_VTHRESH ];
} File_Thresh;
#define Size_File_Thresh ( NB_VTHRESH + NB_VTHRESH )
typedef struct /* format of transistor records in net file */
{
char width[ NB_TSIZE ];
char length[ NB_TSIZE ];
char ttype[ NB_TTYPE ];
char gate[ NB_NDINDEX ];
char src[ NB_NDINDEX ];
char drn[ NB_NDINDEX ];
char x[ NB_COORD ];
char y[ NB_COORD ];
} File_Trans;
#define Size_File_Trans ( NB_TSIZE + NB_TSIZE + NB_TTYPE + \
NB_NDINDEX + NB_NDINDEX + NB_NDINDEX + NB_COORD + NB_COORD )
private tptr wr_nodes()
{
register nptr n;
register tptr txlist;
register lptr l;
File_Node node;
File_Delay delays;
File_Thresh thresh;
int slen;
double cap;
float vhigh = HIGHTHRESH, vlow = LOWTHRESH;
txlist = NULL;
for( n = GetNodeList(); n != NULL; n = n->n.next )
{
cap = n->ncap;
for( l = n->nterm; l != NULL; l = l->next )
{
register tptr t = l->xtor;
if( not (t->tflags & ACTIVE_T) )
{
t->scache.t = txlist;
txlist = t;
t->tflags |= ACTIVE_T;
}
if( t->ttype & GATELIST )
cap += (StackCap( t ) / 2.0);
}
slen = strlen( pnode( n ) ) + 1;
PackBytes( node.slen, slen, NB_STRLEN );
node.flags[0] = n->nflags & SAVE_FLAGS;
if( n->vhigh != vhigh or n->vlow != vlow )
node.flags[0] |= WATCHED;
if( n->nflags & ALIAS )
PackBytes( node.n.alias, Node2index( n->nlink ), NB_NDINDEX )
else
PackBytes( node.n.cap, cap * CAP_SCALE, NB_NCAP );
(void) Fwrite( &node, Size_File_Node, fnet );
(void) Fwrite( pnode( n ), slen, fnet );
if( n->nflags & USERDELAY )
{
PackBytes( delays.tphl, n->tphl, NB_TP );
PackBytes( delays.tplh, n->tplh, NB_TP );
(void) Fwrite( &delays, Size_File_Delay, fnet );
}
if( node.flags[0] & WATCHED )
{
PackBytes( thresh.vhigh, n->vhigh * VTH_SCALE, NB_VTHRESH );
PackBytes( thresh.vlow, n->vlow * VTH_SCALE, NB_VTHRESH );
(void) Fwrite( &thresh, Size_File_Thresh, fnet );
}
}
return( txlist );
}
private void wr_trans( t )
register tptr t;
{
File_Trans trans;
Ulong ndindx;
if( t->ttype & ORED )
{
for( t = t->tlink; t != NULL; t = t->scache.t ) wr_trans( t );
return;
}
ndindx = Node2index( t->gate );
PackBytes( trans.gate, ndindx, NB_NDINDEX );
ndindx = Node2index( t->source );
PackBytes( trans.src, ndindx, NB_NDINDEX );
ndindx = Node2index( t->drain );
PackBytes( trans.drn, ndindx, NB_NDINDEX );
PackBytes( trans.length, t->r->length, NB_TSIZE );
PackBytes( trans.width, t->r->width, NB_TSIZE );
trans.ttype[0] = t->ttype & ~(ORED | ORLIST | STACKED | GATELIST);
if( t->tlink != t )
{
trans.ttype[0] |= GATELIST;
PackBytes( trans.x, t->x.pos, NB_COORD );
PackBytes( trans.y, t->y.pos, NB_COORD );
}
(void) Fwrite( &trans, Size_File_Trans, fnet );
}
private void wr_txtors( tlist )
tptr tlist;
{
register tptr t, next;
for( t = tlist; t != NULL; t = next )
{
next = t->scache.t;
t->tflags &= ~ACTIVE_T;
t->scache.t = NULL;
if( t->ttype & GATELIST )
{
for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
wr_trans( t );
}
else
wr_trans( t );
}
for( t = tcap->dcache.t; t != tcap; t = t->dcache.t )
wr_trans( t );
}
private void WriteAscii( f )
FILE *f;
{
(void) fprintf( f, "lambda %ld\n", LAMBDACM );
(void) fprintf( f, "CTGA %.6f\n", CTGA * CM_M2 );
(void) fprintf( f, "CTDW %.6f\n", CTDW * CM_M );
(void) fprintf( f, "CTDE %.6f\n", CTDE );
/* add extensions here */
(void) fprintf( f, endAscii );
}
private int ReadAscii( f, line )
FILE *f;
char *line;
{
int nl = 0;
inet_CTGA = CTGA;
inet_CTDE = CTDE;
inet_CTDW = CTDW;
inet_lambda = LAMBDACM;
do
{
if( fgetline( line, 200, f ) == NULL )
return( -1 );
nl++;
if( strcmp( line, endAscii ) == 0 )
return( 0 );
if( strncmp( line, "lambda ", 7 ) == 0 )
inet_lambda = atoi( line + 7 );
if( strncmp( line, "CTGA ", 5 ) == 0 )
inet_CTGA = atof( line + 5 ) / CM_M2;
else if( strncmp( line, "CTDW ", 5 ) == 0 )
inet_CTDW = atof( line + 5 ) / CM_M;
else if( strncmp( line, "CTDE ", 5 ) == 0 )
inet_CTDE = atof( line + 5 );
/* add extensions here */
}
while( nl < 30 );
(void) fprintf( stderr, "inet file seems bad\n" );
return( -1 );
}
public void wr_netfile( fname )
char *fname;
{
tptr txlist;
if( (fnet = fopen( fname, "w" )) == NULL )
{
(void) fprintf( stderr, "can't open file '%s'\n", fname );
return;
}
(void) fprintf( fnet, "%s\n", netHeader );
(void) fprintf( fnet, "%d %d\n", GetHashSize(), nnodes + naliases );
WriteAscii( fnet );
txlist = wr_nodes();
wr_txtors( txlist );
(void) fclose( fnet );
}
private void PrematureEof()
{
(void) fprintf( stderr, "premature eof in inet file\n" );
exit( 1 );
}
private void rd_nodes( nname, n_nodes )
char *nname;
int n_nodes;
{
File_Node node;
File_Delay delays;
File_Thresh thresh;
Ulong tmp;
int slen;
nptr n;
nptr aliases;
aliases = NULL;
while( n_nodes-- != 0 )
{
if( Fread( &node, Size_File_Node, fnet ) != Size_File_Node )
PrematureEof();
UnpackBytes( node.slen, slen, NB_STRLEN );
if( Fread( nname, slen, fnet ) != slen )
PrematureEof();
n = GetNode( nname );
n->nflags = node.flags[0];
if( n->nflags & ALIAS )
{
UnpackBytes( node.n.alias, tmp, NB_NDINDEX );
n->c.time = tmp;
n->n.next = aliases;
aliases = n;
}
else
{
UnpackBytes( node.n.cap, tmp, NB_NCAP );
n->ncap = tmp * (1/CAP_SCALE);
if( n->ncap < MIN_CAP )
n->ncap = MIN_CAP;
}
if( n->nflags & USERDELAY )
{
if( Fread( &delays, Size_File_Delay, fnet ) != Size_File_Delay )
PrematureEof();
UnpackBytes( delays.tphl, n->tphl, NB_TP );
UnpackBytes( delays.tplh, n->tplh, NB_TP );
}
if( n->nflags & WATCHED )
{
n->nflags &= ~WATCHED;
if( Fread( &thresh, Size_File_Thresh, fnet ) != Size_File_Thresh )
PrematureEof();
UnpackBytes( thresh.vhigh, tmp, NB_VTHRESH );
n->vhigh = tmp * (1/VTH_SCALE);
UnpackBytes( thresh.vlow, tmp, NB_VTHRESH );
n->vlow = tmp * (1/VTH_SCALE);
}
}
VDD_node->nflags |= INPUT; /* these bits get thrashed above */
GND_node->nflags |= INPUT;
for( n = aliases; n != NULL; n = n->n.next )
{
n->nlink = Index2node( n->c.time );
n->c.time = 0;
nnodes--;
naliases++;
}
}
private void rd_txtors()
{
File_Trans trans;
Ulong ndindx;
long width, length;
tptr t, *last;
rd_tlist = NULL;
last = &rd_tlist;
while( Fread( &trans, Size_File_Trans, fnet ) == Size_File_Trans )
{
NEW_TRANS( t );
UnpackBytes( trans.gate, ndindx, NB_NDINDEX );
t->gate = Index2node( ndindx );
UnpackBytes( trans.src, ndindx, NB_NDINDEX );
t->source = Index2node( ndindx );
UnpackBytes( trans.drn, ndindx, NB_NDINDEX );
t->drain = Index2node( ndindx );
UnpackBytes( trans.width, width, NB_TSIZE );
UnpackBytes( trans.length, length, NB_TSIZE );
t->ttype = trans.ttype[0];
if( t->ttype & GATELIST )
{
t->ttype &= ~GATELIST;
UnpackBytes( trans.x, t->x.pos, NB_COORD );
UnpackBytes( trans.y, t->y.pos, NB_COORD );
EnterPos( t, TRUE );
}
else
EnterPos( t, FALSE );
t->r = requiv( (int) t->ttype, width, length );
ntrans[ BASETYPE( t->ttype ) ] += 1;
*last = t;
last = &(t->scache.t);
}
*last = NULL;
}
public int rd_netfile( f, line )
FILE *f;
char *line;
{
int hash_size, n_nodes;
char *s;
if( strncmp( line, netHeader, HEADER_LEN ) != 0 )
return( FALSE );
if( fgetline( line, 200, f ) == NULL )
PrematureEof();
if( sscanf( line, "%d %d", &hash_size, &n_nodes ) != 2 )
{
(void) fprintf( stderr, "bad format for net file\n" );
exit( 1 );
}
if( hash_size != GetHashSize() )
{
(void) fprintf( stderr, "Incompatible net file version\n" );
exit( 1 );
}
if( ReadAscii( f, line ) ) PrematureEof();
fnet = f;
rd_nodes( line, n_nodes );
rd_txtors();
adjust_transistors( rd_tlist );
return( TRUE );
}
private void adjust_transistors( tlist )
tptr tlist;
{
double adj_g, adj_w, adj_e;
register tptr t;
# define ABS( X ) ( ((X) < 0) ? -(X) : (X) )
# ifndef CAP_ADJUST_LIMIT
# define CAP_ADJUST_LIMIT 0.0000005
# endif
# define G_CAP_ADJUST_LIMIT (CAP_ADJUST_LIMIT / CM_M2)
# define W_CAP_ADJUST_LIMIT (CAP_ADJUST_LIMIT / CM_M)
adj_g = CTGA - inet_CTGA;
adj_w = CTDW - inet_CTDW;
adj_e = CTDE - inet_CTDE;
if( LAMBDACM != inet_lambda and LAMBDACM > 0 and inet_lambda > 0 )
{
double adj_size = (double) LAMBDACM / (double) inet_lambda;
for( t = tlist; t != NULL; t = t->scache.t )
{
t->r->length *= adj_size; t->r->width *= adj_size;
}
}
if( ABS( adj_g ) > G_CAP_ADJUST_LIMIT )
{
for( t = tlist; t != NULL; t = t->scache.t )
t->gate->ncap += adj_g * t->r->length * t->r->width;
}
if( ABS( adj_w ) > W_CAP_ADJUST_LIMIT or ABS( adj_e ) > CAP_ADJUST_LIMIT )
{
for( t = tlist; t != NULL; t = t->scache.t )
{
t->source->ncap += adj_w * t->r->width + adj_e;
t->drain->ncap += adj_w * t->r->width + adj_e;
}
}
}
/*
* Traverse the transistor list and add the node connection-list. We have
* to be careful with ALIASed nodes. Note that transistors with source/drain
* connected to VDD and GND nodes are not linked.
*/
public nptr bin_connect_txtors()
{
register tptr t, tnext;
register nptr nd_list = NULL;
for( t = rd_tlist; t != NULL; t = tnext )
{
tnext = t->scache.t;
t->state = ( t->ttype & ALWAYSON ) ? WEAK : UNKNOWN;
t->tflags = 0;
if( t->ttype & TCAP )
{
LINK_TCAP( t );
}
else
{
if( t->ttype & ALWAYSON )
{
CONNECT( on_trans, t );
}
else
{
CONNECT( t->gate->ngate, t );
}
if( not (t->source->nflags & POWER_RAIL) )
{
CONNECT( t->source->nterm, t );
LINK_TO_LIST( t->source, nd_list, VISITED );
}
if( not (t->drain->nflags & POWER_RAIL) )
{
CONNECT( t->drain->nterm, t );
LINK_TO_LIST( t->drain, nd_list, VISITED );
}
}
}
return( nd_list );
}